package com.zdp.provider.Command;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixThreadPoolKey;

/**
 * 类描述: 服务降级模式：返回远程缓存
 *
 * @author ZhhengDP
 * @since 2021/8/26
 */
public class CommandWithFallbackViaNetwork extends HystrixCommand<String> {

    private final int id;

    public CommandWithFallbackViaNetwork(int id){
        // 通过Setter为 该Command对象设置 Group和key ==> 用于做服务隔离粒度的控制
        super(Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceX"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("GetValueCommand"))
            );

        this.id = id;
    }

    @Override
    protected String run() throws Exception {
        // 抛出异常，得以进入服务降级逻辑
        throw new RuntimeException("服务调用出现异常");
    }

    /**
     * 该服务降级处理的模式是去获取到远程的缓存
     * @return
     */
    @Override
    protected String getFallback() {
        return super.getFallback();
    }

    private static class FallbackViaNetwork extends HystrixCommand<String>{

        private final int id;

        /** 因为该对象时作为CommandWithFallbackViaNetwork的服务降级的处理逻辑
         * 它也是一个远程调用服务，所以也需要用Command对其进行封装。
         * 此外，要注意将其与CommandWithFallbackViaNetwork对象进行区分
         * 使用 group + key + thread pool 来进行区分
         * */
        public FallbackViaNetwork(int id){
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceX"))
            .andCommandKey(HystrixCommandKey.Factory.asKey("GetValueFallbackCommand"))
                    // 使用不同的ThreadPool来执行 fallback command
            .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("RemoteServiceXFallback")));
            this.id = id;
        }

        @Override
        protected String run() throws Exception {
            // 获取到内存缓存中的值
            return null;
        }

        @Override
        protected String getFallback() {
            // 如果失败，就采用静默降级，返回一个空值
            return null;
        }
    }
}
